package cc.shacocloud.mirage.restful.util;

import cc.shacocloud.mirage.restful.HandlerInterceptor;
import cc.shacocloud.mirage.restful.InterceptorMappingInfo;
import cc.shacocloud.mirage.utils.PathMatcher;
import cc.shacocloud.mirage.utils.collection.ArrayUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PathUtil {
    
    /**
     * 默认路径匹配器
     */
    public static final PathMatcher DEFAULT_PATH_MATCHER = new VertxPathMatcher();
    
    /**
     * 返回与指定路径相匹配的拦截器集合
     *
     * @param interceptorMappings 拦截器映射信息集合
     * @param pathMatcher         路径匹配器
     * @param paths               带匹配的路径
     * @return 匹配的拦截器集合
     */
    public static List<HandlerInterceptor> match(List<InterceptorMappingInfo> interceptorMappings,
                                                 PathMatcher pathMatcher,
                                                 String... paths) {
        if (paths == null || paths.length == 0) return null;
        
        List<HandlerInterceptor> interceptors = new ArrayList<>();
        
        for (InterceptorMappingInfo interceptorInfo : interceptorMappings) {
            String[] excludePatterns = interceptorInfo.getExcludePatterns();
            String[] includePatterns = interceptorInfo.getIncludePatterns();
            boolean matches = PathUtil.matches(paths, pathMatcher, excludePatterns, includePatterns);
            if (matches) {
                interceptors.add(interceptorInfo.getHandler());
            }
        }
        return interceptors;
    }
    
    /**
     * 根据给定路径查找是否匹配
     *
     * @param lookupPaths      查找的路径
     * @param pathMatcherToUse 用于路径模式匹配的路径匹配器
     * @param excludePatterns  排除路径模式
     * @param includePatterns  匹配路径模式
     * @return 如果拦截器应用于给定的请求路径，则为{@code true}
     */
    public static boolean matches(String[] lookupPaths,
                                  PathMatcher pathMatcherToUse,
                                  String[] excludePatterns,
                                  String[] includePatterns) {
        if (ArrayUtil.isEmpty(lookupPaths)) return false;
        
        if (!ArrayUtil.isEmpty(excludePatterns)) {
            for (String pattern : excludePatterns) {
                boolean anyMatch = Arrays.stream(lookupPaths).anyMatch(lookupPath -> pathMatcherToUse.match(pattern, lookupPath));
                if (anyMatch) return false;
            }
        }
        
        if (ArrayUtil.isEmpty(includePatterns)) return true;
        
        for (String pattern : includePatterns) {
            boolean anyMatch = Arrays.stream(lookupPaths).anyMatch(lookupPath -> pathMatcherToUse.match(pattern, lookupPath));
            if (anyMatch) return true;
        }
        return false;
    }
    
    
}
